package de.mmis.core.tuplespace;

import java.util.ArrayList;
import java.util.List;

import de.mmis.core.base.Annotations.NoProperty;
import de.mmis.core.base.abstracttree.Tree;
import de.mmis.core.base.event.Observable;

/**
 * This is the interface every Tuplespace(-server) provides. <br/>
 * <b>Important</b>: Each implementing class must copy the annotations of the
 * methods declared herein.
 * 
 * @author Martin Nyolt
 * 
 */
public interface Tuplespace extends Observable<TuplespaceEvent> {

	// /////////////////////////////////////////////////
	// write
	// /////////////////////////////////////////////////
	/**
	 * write tuple into tuplespace
	 * 
	 * @param expression
	 *            expression to write
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void write(Tree expression)
			throws TuplespaceException;

	/**
	 * write expression into tuplespace, which will be deleted after specified
	 * time span
	 * 
	 * @param expression
	 *            expression to write
	 * @param leasetime
	 *            time to live, in milliseconds
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void write(Tree expression, long leasetime)
			throws TuplespaceException;

	// /////////////////////////////////////////////////
	// read/take
	// /////////////////////////////////////////////////
	/**
	 * (blocking) read an expression matching specified pattern from tuplespace,
	 * blocks until such expression is present
	 * 
	 * @param expression
	 *            expression pattern to read
	 * @return read expression
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract Tree read(Tree expression)
			throws TuplespaceException;

	/**
	 * (blocking) read an expression matching specified pattern from tuplespace,
	 * blocks until such expression is present or a timeout occurs
	 * 
	 * @param expression
	 *            expression pattern to read
	 * @param timeout
	 *            maximum time span (in milliseconds) to wait for expression. 0
	 *            means infinite.
	 * @return read expression, or null in case of timeout
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract Tree read(Tree expression, long timeout)
			throws TuplespaceException;

	/**
	 * (non-blocking) read an expression matching specified pattern from
	 * tuplespace if present
	 * 
	 * @param expression
	 *            expression pattern to read
	 * @return read expression, or null if not present
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract Tree readIfExists(Tree expression)
			throws TuplespaceException;

	/**
	 * (blocking) read and remove an expression matching specified pattern from
	 * tuplespace, blocks until such expression is present
	 * 
	 * @param expression
	 *            expression pattern to read
	 * @return read expression
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract Tree take(Tree expression)
			throws TuplespaceException;

	/**
	 * (blocking) read and remove an expression matching specified pattern from
	 * tuplespace, blocks until such expression is present or a timeout occurs
	 * 
	 * @param expression
	 *            expression pattern to read
	 * @param timeout
	 *            maximum time span (in milliseconds) to wait for expression. 0
	 *            means infinite.
	 * @return read expression, or null in case of timeout
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract Tree take(Tree expression, long timeout)
			throws TuplespaceException;

	/**
	 * (non-blocking) read and remove an expression matching specified pattern
	 * from tuplespace if present
	 * 
	 * @param expression
	 *            expression pattern to read
	 * @return read expression, or null if not present
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract Tree takeIfExists(Tree expression)
			throws TuplespaceException;

	// /////////////////////////////////////////////////
	// scan
	// /////////////////////////////////////////////////
	/**
	 * return all tuples in space
	 * 
	 * @return list of all tuples
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract ArrayList<Tree> scan() throws TuplespaceException;

	/**
	 * return all tuples in space, but return at most maxElems tuples
	 * 
	 * @param maxElems
	 *            max. number of tuples to return
	 * @return list of all tuples
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract ArrayList<Tree> scan(int maxElems)
			throws TuplespaceException;

	/**
	 * find all tuples matching specified pattern
	 * 
	 * @param expression
	 *            expression pattern
	 * @return list of found tuples
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract ArrayList<Tree> scan(Tree expression)
			throws TuplespaceException;

	/**
	 * find all tuples matching specified pattern, but return at most maxElems
	 * tuples
	 * 
	 * @param expression
	 *            expression pattern
	 * @param maxElems
	 *            max. number of tuples to return
	 * @return list of found tuples (has maximum length of maxElems)
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract ArrayList<Tree> scan(Tree expression,
			int maxElems) throws TuplespaceException;

	/**
	 * generate an {@link TuplespaceEvent} everytime a change according to the
	 * {@link Notification} occurs.
	 * 
	 * @param notification
	 *            {@link Notification} request
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void notify(Notification notification)
			throws TuplespaceException;

	/**
	 * cancel notification request to tuplespace server
	 * 
	 * @param notification
	 *            notification request
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void unnotify(Notification notification)
			throws TuplespaceException;

	/**
	 * cancel all notification requests to tuplespace server
	 * 
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void unnotifyAll() throws TuplespaceException;

	/**
	 * get all notification requests to tuplespace server
	 * 
	 * @return list of all notification requests
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract List<Notification> getNotifications()
			throws TuplespaceException;

	// /////////////////////////////////////////////////
	// UIDs
	// /////////////////////////////////////////////////
	/**
	 * get and reserve unused unique ID
	 * 
	 * @return unique ID
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	@NoProperty
	public abstract long getUID() throws TuplespaceException;

	/**
	 * reserve specified unique ID
	 * 
	 * @param UID
	 *            unique ID to reserve (must be unused)
	 * @return unique ID
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract long addUID(long UID) throws TuplespaceException;

	/**
	 * cancel specified unique ID reservation
	 * 
	 * @param UID
	 *            unique ID to release
	 * @return unique ID
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract long releaseUID(long UID) throws TuplespaceException;

	// /////////////////////////////////////////////////
	// transactions
	// /////////////////////////////////////////////////
	/**
	 * starts new transaction
	 * 
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void newTransaction() throws TuplespaceException;

	/**
	 * commit last started transaction
	 * 
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void commitTransaction() throws TuplespaceException;

	/**
	 * abort last started transaction
	 * 
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void abortTransaction() throws TuplespaceException;

	// /////////////////////////////////////////////////
	// admin functions
	// /////////////////////////////////////////////////
	/**
	 * resets tuplespace
	 * 
	 * @throws TuplespaceException
	 *             on an invalid request
	 */
	public abstract void resetSpace() throws TuplespaceException;

}